package com.ybear.mvp.util;

import androidx.annotation.Nullable;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;

/**
 * 工具类
 *
 * 查找指定泛型类中持有的Class
 * @see #findHoldClass(Object, Class)
 * 无参构造Class
 * @see #newClass(Class)
 * 带参构造一个泛型的Class
 * @see #newClass(Class, Class[], Object[])
 */
public class MvpUtil {
    /**
     * 查找指定泛型类中持有的Class
     * 传入一个T {@link T} ，它是一个接口/类，在这个T中找到第一个持有 holdCls 的类/接口，将其返回。
     *
     * @param t         需要查找的泛型（它可能是一个接口，也可能是一个类）
     * @param holdCls   持有的Class（它可能是本类，也可能是基类）
     * @param <T>       {@link T}
     * @return          返回 T {@link T} 下所实现的 holdCls
     */
    @Nullable
    public static <T> Class<?> findHoldClass(@Nullable T t, @Nullable Class holdCls) {
        if( t == null || holdCls == null ) return null;
        //遍历实现的所有接口
        for( Class<?> cls : t.getClass().getInterfaces() ) {
            //遍历实现接口所继承的类或者接口
            Class<?> finCls = findGenericInterfaces( cls, holdCls );
            if( finCls != null ) return finCls;
        }
        return null;
    }

    @Nullable
    private static Class<?> findGenericInterfaces(@Nullable Class cls, @Nullable Class holdCls) {
        if( cls == null || holdCls == null ) return null;
        for( Type type : cls.getGenericInterfaces() ) {
            if( !holdCls.equals( type ) ) {
                findGenericInterfaces( cls.getSuperclass(), holdCls );
            }else {
                return cls;
            }
        }
        return null;
    }

    /**
     * 带参构造一个泛型的Class
     * @param cls               构造的Class
     * @param parameterTypes    参数类型    eg: String.class
     * @param args              参数       eg: "AaBb"
     * @param <T>               类的泛型
     * @return                  返回创建好的泛型
     */
    @Nullable
    public static <T> T newClass(@Nullable Class<T> cls,
                                 @Nullable Class<?>[] parameterTypes,
                                 @Nullable Object... args) {
        try {
            if( cls == null ) throw new NullPointerException("newClass -> class or field type is null.");
            //构造对象
            if( parameterTypes == null || args == null || parameterTypes.length != args.length ) {
                return cls.newInstance();
            }else {
                return cls.getConstructor( parameterTypes ).newInstance( args );
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 无参构造Class
     * @param cls   构造的Class
     * @param <T>   类的泛型
     * @return      返回创建好的泛型
     */
    @Nullable
    public static <T> T newClass(Class<T> cls) {
        return newClass(cls, null, (Object) null);
    }

    public static Class<?>[] toClss(Class<?>... clss) { return clss; }
    public static Object[] toObjs(Object... obj) { return obj; }

    /**
     * 查找根父类（最终继承的父类）
     * @param cls   {@link Class}
     * @return      最终的父类
     */
    @Nullable
    public static Class<?> findRootSuperclass(@Nullable Class<?> cls) {
        Class<?> suCls;
        if( cls == null ) return null;
        suCls = cls.getSuperclass();
        return suCls == null || Object.class.equals( suCls ) ? cls : findRootSuperclass( suCls );
    }
}

